package com.epam.training.concurrency.second.task3;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Test class
 * 
 * @author bogdan
 *
 */
public class Test {

	private Test() {

	}

	public static void main(String[] args) {
		ConectionPool pool = new ConectionPool("jdbc:h2:~/test;IFEXISTS=TRUE",
				"sa", "");

		try {
			pool.startPool();

			WrapConnection[] con = new WrapConnection[10];

			for (int i = 0; i < 10; i++) {
				con[i] = pool.checkOut();
			}

			try {
				PreparedStatement state = con[0]
						.prepareStatement("CREATE TABLE PUBLIC.TEST_TABLE (COL1 INTEGER NOT NULL, COL2 CHAR(25), COL3 VARCHAR(25) NOT NULL, COL4 DATE, PRIMARY KEY (COL1));IFEXISTS=TRUE");
				state.executeUpdate();
			} finally {
				con[0].close();
			}

			try {
				Thread.currentThread().join();
			} catch (InterruptedException e1) {
				Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null,
						e1);
			}

			for (int i = 0; i < 5; i++) {
				try {
					new Thread(new ThreadQuery(pool.checkOut())).start();
				} catch (InterruptedException e) {
					Logger.getLogger(Test.class.getName()).log(Level.SEVERE,
							"Pool shutdown error", e);
				}
			}

			try {
				TimeUnit.MILLISECONDS.sleep(10000);
				pool.shutdown();
			} catch (InterruptedException | SQLException e) {
				Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null,
						e);
			}
		} catch (SQLException | InterruptedException | ClassNotFoundException e1) {
			Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, e1);
		} finally {
			try {
				pool.shutdown();
			} catch (SQLException e) {
				Logger.getLogger(Test.class.getName()).log(Level.SEVERE,
						"Pool shutdown error", e);
			}
		}
	}

	private static class ThreadQuery implements Runnable {
		private WrapConnection con;
		private static final String query = "SELECT * FROM PUBLIC.TEST_TABLE";

		public ThreadQuery(WrapConnection connection) {
			con = connection;
		}

		@Override
		public void run() {
			PreparedStatement state;
			try {
				state = con.prepareStatement(query);
				state.executeQuery();
			} catch (SQLException e) {
				Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null,
						e);
			} finally {
				try {
					con.close();
				} catch (SQLException e) {
					Logger.getLogger(Test.class.getName()).log(Level.SEVERE,
							"Connection close error", e);
				}
			}
		}

	}
}
